// Copyright 2018 Intel Corporation. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package deviceplugin provides API for reporting available devices to kubelet.
package deviceplugin

import (
	pluginapi "k8s.io/kubelet/pkg/apis/deviceplugin/v1beta1"
)

// DeviceInfo contains information about device maintained by Device Plugin.
type DeviceInfo struct {
	mounts      []pluginapi.Mount
	envs        map[string]string
	annotations map[string]string
	health      string
	devices     []pluginapi.DeviceSpec
}

// NewDeviceInfo makes DeviceInfo struct and adds topology information to it.
func NewDeviceInfo(state string, devices []pluginapi.DeviceSpec, mounts []pluginapi.Mount, envs, annotations map[string]string) DeviceInfo {
	deviceInfo := DeviceInfo{
		health:      state,
		devices:     devices,
		mounts:      mounts,
		envs:        envs,
		annotations: annotations,
	}

	return deviceInfo
}

// AddDevice adds device info to DeviceTree.
func (tree DeviceTree) AddDevice(devType, id string, info DeviceInfo) {
	if _, present := tree[devType]; !present {
		tree[devType] = make(map[string]DeviceInfo)
	}

	tree[devType][id] = info
}

// DeviceTree contains a tree-like structure of device type -> device ID -> device info.
type DeviceTree map[string]map[string]DeviceInfo

// NewDeviceTree creates an instance of DeviceTree.
func NewDeviceTree() DeviceTree {
	return make(map[string]map[string]DeviceInfo)
}

// Notifier receives updates from Scanner, detects changes and sends the
// detected changes to a channel given by the creator of a Notifier object.
type Notifier interface {
	// Notify notifies manager with a device tree constructed by device
	// plugin during scanning process.
	Notify(DeviceTree)
}

// Scanner serves as an interface between Manager and a device plugin.
type Scanner interface {
	// Scan scans the host for devices and sends all found devices to
	// a Notifier instance. It's called only once for every device plugin by
	// Manager in a goroutine and operates in an infinite loop.
	Scan(Notifier) error
}
